# -*- coding:utf-8 -*-
import os,sys
import openpyxl

from app.common.global_values import *

from app.features.service.sheet_info import SheetInfo
from app.features.service.sheet_analysis_util import SheetAnalysisUtil
from app.features.service.export_util.export_json_util import TableExportToJsonUtil

class ExportService:
    """
    导出主业务逻辑
    """
    def __init__(self, controller):
        # 控制器（能操作到view 和 model）
        self.controller = controller
        # 导出文件名和文件信息
        self.excel_file_dict = {}
        # 导出文件表名称和文件信息
        self.export_tableName_path_dict = {}
        # 使用的工具类
        self.table_analysis_util = SheetAnalysisUtil()
        self.export_to_json_util = TableExportToJsonUtil(controller)

        # 需要处理的每张Excel表格 名称和 解析后的数据映射表 key 表名 value 解析后的 SheetInfo 数据
        self.tableInfo = {}

    def _progressDisplay(self, msg, level):
        """
        消息更新到ui log显示中
        """
        self.controller.model.add_log(msg)

    def _get_all_excel(self, inputdir):
        """
        获取目录下所有的excel文件
        params:
            inputdir excel文件所在目录路径

        return excel 文件名全路径列表
        """
        excel_file_list = []
        list = os.listdir(inputdir)  # 列出文件夹下所有的目录与文件
        for i in range(0, len(list)):
            path = str(os.path.join(inputdir, list[i]))
            if os.path.isfile(path) and path.endswith('.xlsx'):
                excel_file_list.append(path)
        return excel_file_list

    def _check_input_and_output_dir(self, inputdir, outputdir, outputtype):
        """
        检查输入和输出目录,没有输出目录则创建目录
        """
        # 检查excel目录文件夹是否存在,不存在退出
        if not os.path.exists(inputdir):
            return False
        # 检查输出文件夹是否存在,不存在创建,to+type参数
        for typedir in outputtype:
            typedirName = "to"+typedir
            outputdir = os.path.join(outputdir, typedirName)
            if not os.path.exists(outputdir):
                os.mkdir(outputdir)
        return True

    def _check_duplicate_name_file(self, excel_file_list):
        """
        检查是否有重复的excel文件
        """
        # 展示重复元素
        for file_name in excel_file_list:
            # 排除在排除配置文件列表
            base_name = str(os.path.basename(file_name)).strip()
            if base_name in ExceptExportTableNames:
                continue
            # 排除临时文件(~开头)
            if base_name.startswith(EXCEL_TEMP_FILE_FILE_NAME_START_STRING):
                continue
            # 加入到需要处理的文件列表(key 文件名称, value 文件路径)
            if base_name in self.excel_file_dict:
                self._progressDisplay(f"有重名的excel文件:{file_name}", "ERROR")
                return True
            self.excel_file_dict[base_name] = file_name
                
        return False 

    def _parse_excel(self):
        """
        解析excel文件到自定统一格式
        """
        for base_name, file_name in self.excel_file_dict.items():
            # 加入到需要处理的文件列表(key 文件名称, value 文件路径)
            self.export_tableName_path_dict[base_name] = file_name
            self._progressDisplay(f"需要处理的文件:{file_name} 分析sheet名称", "INFO")
        # 循环处理excel文件,读取excel文件,解析为自定义的类,方便后续对数据进行转换(key:文件名basename, value:文件路径)
        for tableName, filePath in self.export_tableName_path_dict.items():
            # 读取excel
            workbook = openpyxl.load_workbook(filePath)
            for sheetname in workbook.sheetnames:
                # 定位到data表,会有多个sheet比如config对data的描述和说明
                if sheetname == EXCEL_DATA_SHEET_NAME:
                    sheet = workbook[sheetname] 
                    # 调用sheet分析处理逻辑,将sheet的内容,解析成一个完整的SheetInfo
                    tableInfo, errorMsg = self.table_analysis_util.analysis(sheet, file_name)
                    if tableInfo == None or len(errorMsg) > 1:
                        self._progressDisplay(f"excel:{file_name} 解析失败, 原因:{errorMsg}", "ERROR")
                        return False
                    # 加入到映射关系，后续导出遍历用
                    self.tableInfo[tableName] = SheetInfo
        return True
    
    def export(self):
        """
        实现具体导出的方法,参数说明:
            view_log ui 日志显示用的实例
            excel_dir   excel文件所在目录
            save_dir    导出文件的父目录
            export_type 导出类型数组,在导出父目录下创建对应导出类型的文件名,导出文件到目录内
        """
        excel_dir = self.controller.model.excel_dir
        export_dir = self.controller.model.export_dir
        delimiter = self.controller.model.delimiter
        export_type = self.controller.model.export_type.split(",")    
        # 检查输入输出目录
        if not self._check_input_and_output_dir(excel_dir, export_dir, export_type):
            self._progressDisplay(f"据目录:{excel_dir}不存在", "ERROR")
            sys.exit()
        # 获取文件夹内所有的excel文件名称列表
        excel_file_list = self._get_all_excel(excel_dir)
        if len(excel_file_list) < 1:
            self._progressDisplay(f"数据目录:{excel_dir}没有任何文件", "ERROR")
            sys.exit()
        # 检查是否有同名excel文件,有报错,展示重复元素(有重名会退出程序)
        if self._check_duplicate_name_file(excel_file_list):
            self._progressDisplay('有重名的excel文件', "ERROR")
            sys.exit()
        # 分析那些文件需要处理
        if self._parse_excel() == False: 
            self._progressDisplay('解析excel文件失败', "ERROR")
            sys.exit()
        # 根据导出类型参数,调用对应的导出处理方法,导出对应的文件
        self._progressDisplay('根据选项导出成对应的格式', "INFO")
        for tableName, filePath in self.export_tableName_path_dict.items():
            tableInfo:SheetInfo = self.tableInfo[tableName]
            self._progressDisplay(f"导出表格:{tableInfo.tableName}", "INFO")
            if "Json" in export_type:
                self._progressDisplay("导出Json格式", "INFO")
                self.export_to_json_util.export_to_json(tableInfo)
            # elif 扩展其他语言 
            # elif "python" in export_type:
            #   pass
            # elif "golang" in export_type:
            #   pass
            # elif "java" in export_type:
            #   pass
            # elif "csharp" in export_type:
            #   pass
        sys.exit()